/*
 * 需要注意   (已经修改 默认携带请求头，想要不携带请求头token 你就true )
 * 本地有token 并且 请求头isToken等于true 则携带token
 * 
 * 网络请求思路 => 生产的token令牌保存在cookie里   请求中需要token(令牌)则 带上cookie里的令牌 
 * 也就是说 本地的cookie是用来存储令牌的而已  通信需要请求头中有令牌就行
 * 
 * 是否需要防止数据重复提交 headers中 repeatSubmit 为 false 则需要防止重复提交, true则不需要防止
 * 
 * 登录=》颁发token 使用时携带token 
 */

import Vue from 'vue';
import axios from 'axios';

import store from '@/store';

import {
  getToken,
  setToken,
  removeToken,
} from '@/utils/token';
//错误代码
import errorCode from '@/utils/errorCode';
//好用的工具类
import {
  tansParams,
  blobValidate
} from '@/utils/tool';

//若依本地存储操作
import cache from '@/utils/token';
//好用的下载
import {
  saveAs
} from 'file-saver'
import router from '@/router';

import NProgress from "nprogress";


// 默认的请求地址
// axios.defaults.baseURL = 'http://127.0.0.1:3007/';
// 是否显示重新登录
// export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';

const service = axios.create({
  // axios中请求配置有baseURL选项，表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 60000
})


// 前置守卫 挂载token
service.interceptors.request.use(config => {
  NProgress.start();

  // 是否需要设置 token    headers中 isToken 为 false 则不需要token, true则需要token
  const isToken = !((config.headers || {}).isToken === false); //我自己改成true
  // 是否需要防止数据重复提交 headers中 repeatSubmit 为 false 则需要防止重复提交, true则不需要防止
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false

  //有token 并且 请求头需要token 则携带token
  if (getToken() && isToken) {
    config.headers['Authorization'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  }

  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }

  //post 和 put 的请求防止刷新
  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    //兼容数据 提交的是obj自动转换
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
    }
    //如果sessionObj当前是空的 则写入当前的请求和数据进去，临时回话
    //如果不是空的 直接读取临时会话数据 和当前请求做对比
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {
      //如果 会话中的data 等于当前的data 并且 会话的时间距离这次时间小于interval 并且 会话的请求地址等于当前请求地址
      const s_url = sessionObj.url; // 请求地址
      const s_data = sessionObj.data; // 请求数据
      const s_time = sessionObj.time; // 请求时间
      const interval = 1000; // 间隔时间(ms)，小于此时间视为重复提交
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理，请勿重复提交';
        console.warn(`[${s_url}]: ` + message)
        return Promise.reject(new Error(message))
      } else {
        //否则不是频繁提交的话，保存本次请求到会话
        cache.session.setJSON('sessionObj', requestObj)
      }
    }
  }

  return config;
}, error => {
  console.log(error)
  Promise.reject(error)
})

//后置守卫
service.interceptors.response.use(config => {
  NProgress.done();
  if(config.data.message =='身份认证失败！'){
    Vue.prototype.$message.error('身份过期啦！')
    removeToken()
    Vue.prototype.$cache.local.remove('userinfo')
    router.replace({
      path: `/login?path=${router.currentRoute.fullPath}`
    })
  }


  return config
}, async function (error) { // 响应状态码4xx/5xx进这里
  // 对响应错误做点什么
  // console.dir(error)

  if (error.response.status === 401) { // 身份过期
    // token续签方式1:  去登录页重新登录, token无用, 清掉-确保路由守卫if进不去
    //提示过期
    Vue.prototype.$message.error('身份过期啦！')
    removeToken()
    Vue.prototype.$cache.local.remove('userinfo')
    router.replace({
      path: `/login?path=${router.currentRoute.fullPath}`
    })

    return
    // 
    // token续签方式2: refreshToken(用户无感知)
    // store.commit('setToken', '')
    // const res = await refreshTokenAPI()
    // store.commit('setToken', res.data.data.token)

    // 再调用一次未完成的请求啊(用户无感知)
    // error.config 就是上一次axios请求的配置对象
    // console.dir(error.config)
    // 把新的token赋予到下一次axios请求的请求头中
    // error.config.headers.Authorization = 'Bearer ' + res.data.data.token
    // return到await的地方
    // return axios(error.config)
  } else if (error.response.status === 500 && error.config.method === 'put') {
    Vue.prototype.$cache.local.remove('userinfo')

    // 都过期了
    // Notify('身份已过期')
    // router.replace({
    //     path: '/login'
    // })
    // router.replace({
    //     path: `/login?path=${router.currentRoute.fullPath}`
    // })
  } else {
    return Promise.reject(error)
  }
})

//挂载
Vue.prototype.$http = service


export default service